package com.sh.apibackend.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.sh.apibackend.common.ErrorCode;
import com.sh.apibackend.exception.BusinessException;
import com.sh.apibackend.mapper.UserInterfaceInfoMapper;
import com.sh.apibackend.model.userinterface.UpdateUserInterfaceInfoDTO;
import com.sh.apibackend.model.userinterfaceinfo.UpdateInvokeToJMS;
import com.sh.apibackend.model.vo.InterfaceInfoVo;
import com.sh.apibackend.model.vo.UserInterfaceInfoVO;
import com.sh.apibackend.service.InterfaceInfoService;
import com.sh.apibackend.service.UserInterfaceInfoService;
import com.sh.apibackend.service.UserService;
import com.sh.apicommon.entity.InterfaceInfo;
import com.sh.apicommon.entity.User;
import com.sh.apicommon.entity.UserInterfaceInfo;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 舒云
 * @description 针对表【user_interface_info】的数据库操作Service实现
 * @createDate 2024-10-02 20:15:33
 */
@Service
@Slf4j
public class UserInterfaceInfoServiceImpl extends ServiceImpl<UserInterfaceInfoMapper, UserInterfaceInfo>
        implements UserInterfaceInfoService {
    @Resource
    private UserInterfaceInfoMapper userInterfaceInfoMapper;
    @Resource
    private UserService userService;
    @Resource
    private InterfaceInfoService interfaceInfoService;

    @Resource // 自动注入 JmsTemplate 实例
    private JmsTemplate jmsTemplate;

    @Value(value = "${invokeCountToJMS}") // 从配置文件中注入队列名称
    private String queueName;

    /**
     * 统计 || 修改  接口调用次数
     * @param userId
     * @param interfaceInfoId
     * @return
     */
    @Override
    public boolean invokeCount(long userId, long interfaceInfoId) {
        //校验用户id，接口id是否合理
        //校验用户的接口剩余调用次数是否充足
        //接口总调用次数+1，剩余调用次数-1
        if (userId < 0 || interfaceInfoId < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户或接口信息不存在");
        }

        QueryWrapper<UserInterfaceInfo> userInterfaceInfoQueryWrapper = new QueryWrapper<>();
        userInterfaceInfoQueryWrapper.eq("userId", userId);
        userInterfaceInfoQueryWrapper.eq("interfaceInfoId", interfaceInfoId);
        UserInterfaceInfo userInterfaceInfo = userInterfaceInfoMapper.selectOne(userInterfaceInfoQueryWrapper);
        Integer version = userInterfaceInfo.getVersion();
        Integer leftNum = userInterfaceInfo.getLeftNum();
        if (leftNum <= 0) {
            log.error("接口调用次数不足");
            return false;
        }
        UpdateWrapper<UserInterfaceInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("userId", userId);
        updateWrapper.eq("interfaceInfoId", interfaceInfoId);
        updateWrapper.eq("version", version);
        updateWrapper.gt("leftNum", 0);
        updateWrapper.setSql("totalNum = totalNum + 1 , leftNum = leftNum - 1 , version = version + 1");
        boolean update = this.update(updateWrapper);
        return update;
        // todo 消息队列
    }


    /**
     * 根据用户id获取接口信息  列表
     *
     * @param userId
     * @param request
     * @return
     */
    @Override
    public List<UserInterfaceInfoVO> getInterfaceInfoByUserId(Long userId, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);        // 获取登录用户
        if (!loginUser.getId().equals(userId)) {  // 如果传入的id值，不是当前登录用户的id，则抛出无权限异常
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            // todo 判断管理员权限
        }
        QueryWrapper<UserInterfaceInfo> userInterfaceInfoQueryWrapper = new QueryWrapper<>();
        userInterfaceInfoQueryWrapper.eq("userId", loginUser.getId());
        List<UserInterfaceInfo> userInterfaceInfoList = this.list(userInterfaceInfoQueryWrapper);

        //        list
        Map<Long, List<UserInterfaceInfo>> interfaceIdUserInterfaceInfoMap = userInterfaceInfoList.stream().collect(Collectors.groupingBy(UserInterfaceInfo::getInterfaceInfoId));

        Set<Long> interfaceIds = interfaceIdUserInterfaceInfoMap.keySet();
        QueryWrapper<InterfaceInfo> interfaceInfoQueryWrapper = new QueryWrapper<>();
        if (CollectionUtil.isEmpty(interfaceIds)) {
            return new ArrayList<>();
        }
        interfaceInfoQueryWrapper.in("id", interfaceIds);
        List<InterfaceInfo> interfaceInfoList = interfaceInfoService.list(interfaceInfoQueryWrapper);
        List<UserInterfaceInfoVO> userInterfaceInfoVOList = interfaceInfoList.stream().map(interfaceInfo -> {
            UserInterfaceInfoVO userInterfaceInfoVO = new UserInterfaceInfoVO();
            // 复制接口信息
            BeanUtils.copyProperties(interfaceInfo, userInterfaceInfoVO);
            userInterfaceInfoVO.setInterfaceStatus(Integer.valueOf(interfaceInfo.getStatus()));

            // 复制用户调用接口信息
            List<UserInterfaceInfo> userInterfaceInfos = interfaceIdUserInterfaceInfoMap.get(interfaceInfo.getId());
            UserInterfaceInfo userInterfaceInfo = userInterfaceInfos.get(0);
            BeanUtils.copyProperties(userInterfaceInfo, userInterfaceInfoVO);
            return userInterfaceInfoVO;
        }).collect(Collectors.toList());
        return userInterfaceInfoVOList;
        // todo ;;;;;;
    }


    /**
     * 更新用户接口信息, 就是更新用户接口信息的总数和剩余数
     * @param updateUserInterfaceInfoDTO
     * @return
     */
    @Override
    public boolean updateUserInterfaceInfo(UpdateUserInterfaceInfoDTO updateUserInterfaceInfoDTO) {
        Long userId = updateUserInterfaceInfoDTO.getUserId();
        Long interfaceId = updateUserInterfaceInfoDTO.getInterfaceId();
        Long lockNum = updateUserInterfaceInfoDTO.getLockNum();
        if (interfaceId == null || userId == null || lockNum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        QueryWrapper<UserInterfaceInfo> userInterfaceInfoQueryWrapper = new QueryWrapper<>();
        userInterfaceInfoQueryWrapper.eq("userId", userId);
        userInterfaceInfoQueryWrapper.eq("interfaceInfoId", interfaceId);
        UserInterfaceInfo one = getOne(userInterfaceInfoQueryWrapper);   // 拿到这条数据

        if (one != null) {  // 如果存在这条数据
            UpdateWrapper<UserInterfaceInfo> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("userId", userId);
            updateWrapper.eq("interfaceInfoId", interfaceId);
            updateWrapper.setSql("leftNum = leftNum + " + lockNum);
            boolean update = this.update(updateWrapper);
            return update;
        } else {  // 如果不存在这条数据 新建
            UserInterfaceInfo userInterfaceInfo = new UserInterfaceInfo();
            userInterfaceInfo.setUserId(userId);
            userInterfaceInfo.setInterfaceInfoId(interfaceId);
            userInterfaceInfo.setLeftNum(lockNum.intValue());
            boolean save = this.save(userInterfaceInfo);
            return save;
        }
    }

    @Override
    public List<InterfaceInfoVo> interfaceInvokeTopAnalysis(int limit) {
        List<UserInterfaceInfo> userInterfaceInfoList = userInterfaceInfoMapper.listTopInvokeInterfaceInfo(limit);
        Map<Long, List<UserInterfaceInfo>> interfaceInfoIdObjMap = userInterfaceInfoList.stream()
                .collect(Collectors.groupingBy(UserInterfaceInfo::getInterfaceInfoId));
        QueryWrapper<InterfaceInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", interfaceInfoIdObjMap.keySet());
        List<InterfaceInfo> list = interfaceInfoService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }

        List<InterfaceInfoVo> interfaceInfoVOList = list.stream().map(interfaceInfo -> {
            InterfaceInfoVo interfaceInfoVO = new InterfaceInfoVo();
            BeanUtils.copyProperties(interfaceInfo, interfaceInfoVO);
            int totalNum = interfaceInfoIdObjMap.get(interfaceInfo.getId()).get(0).getTotalNum();
            interfaceInfoVO.setTotalNum(totalNum);
            return interfaceInfoVO;
        }).collect(Collectors.toList());
        return interfaceInfoVOList;
    }
}




